home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / emula / arosdv19.lha / AROS / exec / releasesemaphore.c < prev    next >
C/C++ Source or Header  |  1996-10-24  |  4KB  |  160 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: releasesemaphore.c,v 1.6 1996/10/24 15:50:54 aros Exp $
  4.     $Log: releasesemaphore.c,v $
  5.     Revision 1.6  1996/10/24 15:50:54  aros
  6.     Use the official AROS macros over the __AROS versions.
  7.  
  8.     Revision 1.5  1996/09/13 17:51:24  digulla
  9.     Use IPTR
  10.  
  11.     Revision 1.4  1996/08/13 13:56:05  digulla
  12.     Replaced AROS_LA by AROS_LHA
  13.     Replaced some AROS_LH*I by AROS_LH*
  14.     Sorted and added includes
  15.  
  16.     Revision 1.3  1996/08/01 17:41:16  digulla
  17.     Added standard header for all files
  18.  
  19.     Desc:
  20.     Lang: english
  21. */
  22. #include "exec_intern.h"
  23. #include "semaphores.h"
  24.  
  25. /*****************************************************************************
  26.  
  27.     NAME */
  28.     #include <exec/semaphores.h>
  29.     #include <clib/exec_protos.h>
  30.  
  31.     AROS_LH1(void, ReleaseSemaphore,
  32.  
  33. /*  SYNOPSIS */
  34.     AROS_LHA(struct SignalSemaphore *, sigSem, A0),
  35.  
  36. /*  LOCATION */
  37.     struct ExecBase *, SysBase, 95, Exec)
  38.  
  39. /*  FUNCTION
  40.     Releases a lock on a semaphore obtained with either ObtainSemaphore(),
  41.     ObtainSemaphoreShared(), AttemptSemaphore or AttemptSemaphoreShared().
  42.     Each call to one of those functions must be accompanied with one
  43.     call to ReleasSemaphore().
  44.  
  45.     INPUTS
  46.     sigSem - pointer to semaphore structure
  47.  
  48.     RESULT
  49.  
  50.     NOTES
  51.     This function preserves all registers.
  52.  
  53.     EXAMPLE
  54.  
  55.     BUGS
  56.  
  57.     SEE ALSO
  58.  
  59.     INTERNALS
  60.  
  61.     HISTORY
  62.     29-10-95    digulla automatically created from
  63.                 exec_lib.fd and clib/exec_protos.h
  64.     22-01-96    fleischer implementation
  65.  
  66. *****************************************************************************/
  67. {
  68.     AROS_LIBFUNC_INIT
  69.     AROS_LIBBASE_EXT_DECL(struct ExecBase *,SysBase)
  70.  
  71.     /* Arbitrate for the semaphore structure */
  72.     Forbid();
  73.  
  74.     /* Lower the use count. >0 means exclusive, <0 shared locked */
  75.     if(sigSem->ss_NestCount>0)
  76.     sigSem->ss_NestCount--;
  77.     else
  78.     sigSem->ss_NestCount++;
  79.  
  80.     /*
  81.     Now if the semaphore is free and there are other tasks waiting
  82.     wake them up.
  83.     */
  84.     if(!sigSem->ss_NestCount&&sigSem->ss_WaitQueue.mlh_Head->mln_Succ!=NULL)
  85.     {
  86.     /* Get first node in the waiting list */
  87.     struct SemaphoreNode *sn;
  88.     sn=(struct SemaphoreNode *)sigSem->ss_WaitQueue.mlh_Head;
  89.  
  90.     /* Is it a shared lock? */
  91.     if((IPTR)sn->node.ln_Name!=SM_EXCLUSIVE)
  92.     {
  93.         /* Yes. Process all shared locks in the list. */
  94.         while(sn->node.ln_Succ!=NULL)
  95.         {
  96.         /* Remember node */
  97.         struct SemaphoreNode *on=sn;
  98.  
  99.         /* Get next node now because there is a Remove() lurking */
  100.         sn=(struct SemaphoreNode *)sn->node.ln_Succ;
  101.  
  102.         /* Is this a shared lock? */
  103.         if((IPTR)on->node.ln_Name!=SM_EXCLUSIVE)
  104.         {
  105.             /* Yes. Remove it from the list */
  106.             Remove(&on->node);
  107.  
  108.             /* Wake the new owner. Check access type. */
  109.             if(on->node.ln_Pri==SN_TYPE_OBTAIN)
  110.             /* ObtainSemaphore() type. Send the semaphore signal. */
  111.             Signal(on->task,SEMAPHORESIGF);
  112.             else
  113.             {
  114.             /* Procure() type. Reply the semaphore message. */
  115.             ((struct SemaphoreMessage *)on)->ssm_Semaphore=sigSem;
  116.             ReplyMsg((struct Message *)on);
  117.             }
  118.  
  119.             /*
  120.             Mark the semaphore as having one more openers.
  121.             This happens here because the new owner(s) may need
  122.             some time to really wake up and I don't want other
  123.             tasks obtaining the semaphore before him.
  124.             */
  125.             sigSem->ss_NestCount--;
  126.         }
  127.         /* Dito. Invalidate the owner field. */
  128.         sigSem->ss_Owner=NULL;
  129.         }
  130.     }else
  131.     {
  132.         /* The new owner wants an exclusive lock. Remove him from the list. */
  133.         Remove(&sn->node);
  134.  
  135.         /* Check access type */
  136.         if(sn->node.ln_Pri==SN_TYPE_OBTAIN)
  137.         {
  138.         /*
  139.             ObtainSemaphore() type. Set the owner field and
  140.             Send the semaphore signal.
  141.         */
  142.         sigSem->ss_Owner=sn->task;
  143.         Signal(sn->task,SEMAPHORESIGF);
  144.         }else
  145.         {
  146.         /* Procure() type. Reply the message. */
  147.         ((struct SemaphoreMessage *)sn)->ssm_Semaphore=sigSem;
  148.         sigSem->ss_Owner=((struct Message *)sn)->mn_ReplyPort->mp_SigTask;
  149.         ReplyMsg((struct Message *)sn);
  150.         }
  151.         /* Mark the semaphore as having one more openers. */
  152.         sigSem->ss_NestCount++;
  153.     }
  154.     }
  155.  
  156.     /* All done. */
  157.     Permit();
  158.     AROS_LIBFUNC_EXIT
  159. } /* ReleaseSemaphore */
  160.